/**
 * index.html 配置文件
 */
const Query = {
    data() {
        return {
            Total: 0,//总数
            columns: [{
                COLUMN_COMMENT: '暂未配置数据源',
                Column_Align: 'center'
            }],//表头数据
            tableData: [], //表格数据
            treeData: [], //树状图数据
            buttonRole: {}, //按钮权限
            loading: false,//节流开关
            isExport: false,//导出节流开关
            isUpdate: true,//更新表格
            dialogFieldVisible: false,//自定义字段开关
        }
    },
    mounted() {
        this.getColumn();
        this.getTreeData();
    },
    methods: {
        handleAdd() {// 点击添加
            window.location.href = "./add.html?action=Add"
        },
        handleEdit(row) {// 点击修改
            try {
                const { primaryKey } = $('#table').data('options');
                window.location.href = "./add.html?action=Modify&nodeKey=" + row[primaryKey];
            } catch (error) {
                console.error(error);
                this.$message({
                    message: '系统错误，请联系开发者!',
                    type: 'error'
                })
            }
        },
        handleRemove(row) { // 点击删除
            this.$confirm('警告！此操作将删除该数据, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning',
            }).then(async () => {
                try {
                    const { tableName, primaryKey } = $('#table').data('options');
                    let data = await generalApi.generalQueryByTableNameWithOriginal({
                        Data: tableName,
                        Condition: `${primaryKey}='${row[primaryKey]}'`
                    })
                    if (data.length == 1) {
                        data[0].Row_Status = '1';
                        let lJSONObject_Modify = new Object();
                        lJSONObject_Modify[tableName] = data;
                        //组合
                        let lJSONObject_DataSet = {
                            Modify: lJSONObject_Modify, Add: {}
                        };
                        let Operation_Main = JSON.stringify(deepClone(lJSONObject_DataSet));
                        lJSONObject_DataSet['Add']['base_operation_log'] = [{
                            Operation_Type: '0',
                            Operation_Path: getRelativePath(),
                            Operation_Description: '删除数据',
                            Operation_Main,
                            Operation_Interface: "generalSaveByRequestBody",
                            Operation_IP: getIpAddress()
                        }]
                        const res = await generalApi.generalSaveByRequestBody({
                            Data: lJSONObject_DataSet
                        })
                        if (res.Status == "success") {
                            this.getList(this.form);
                            this.$message.success("删除成功");
                        } else {
                            this.$message.error("删除失败，请重试！");
                        }
                    }
                } catch (error) {
                    console.error(error);
                    this.$message({
                        message: '系统错误，请联系开发者!',
                        type: 'error'
                    })
                }
            }).catch(() => { });
        },
        handleCommand(val, row) {// 下单选项卡
            try {
                this[val](row);
            } catch (error) {
                this.$message({
                    message: '该事件不存在，请联系开发者!',
                    type: 'error'
                })
            }
        },
        handleSelectionChange() { },// 当表格有多选框时，点击多选框
        handleNodeClick() { },// 当页面有树状图时，点击树节点
        async handleExport() {// 点击批量导出
            this.isExport = true;
            try {
                const { tableName } = $('#table').data('options');
                const data = this.form;
                const xlsx_header = {
                    SQLSerialNumber: 's_base_sql_table_config',
                    Condition: utf8ToBase64(`${getCookie('user')},%${getRelativePath()}%,${getCookie('user')},%${getRelativePath()}%`),
                    ExtensionCondition: ''
                };
                const xlsx_main = {
                    Model_Url: getRelativePath(),
                    Condition: data.Condition,
                    ExtensionCondition: data.ExtensionCondition || ''
                }
                const columns = await generalApi.generalQueryBySQLSerialNumber(xlsx_header);
                if (columns.length > 0) {
                    const data = await generalApi.generalQueryBySQLSerialNumber(xlsx_main);
                    this.isExport = false;
                    if (data.length > 0) {
                        this.$confirm(`当前共查出${data.length}条数据, 是否继续?`, '提示', {
                            confirmButtonText: '确定',
                            cancelButtonText: '取消',
                            type: 'success',
                        }).then(async () => {
                            const wb = XLSX.utils.book_new();
                            const ws_data = [columns.map(i => i.COLUMN_COMMENT)];
                            const ws_main = data.map(item => columns.map(row => item[row.COLUMN_NAME]));
                            const ws = XLSX.utils.aoa_to_sheet([...ws_data, ...ws_main]);
                            ws['!cols'] = [];
                            for (let i = 0; i < Object.keys(ws_data[0]).length; i++) {
                                ws['!cols'].push({ wpx: 150 });
                            };
                            XLSX.utils.book_append_sheet(wb, ws, tableName);
                            XLSX.writeFile(wb, tableName + (+new Date()) + ".xlsx");
                            //日志记录导出
                            let lJSONObject_DataSet = { Add: {} };
                            let Operation_Main = JSON.stringify(deepClone({ xlsx_header, xlsx_main }));
                            lJSONObject_DataSet['Add']['base_operation_log'] = [{
                                Operation_Type: '0',
                                Operation_Path: getRelativePath(),
                                Operation_Description: '导出数据',
                                Operation_Main,
                                Operation_Interface: "generalQueryBySQLSerialNumber",
                                Operation_IP: getIpAddress()
                            }]
                            const res = await generalApi.generalSaveByRequestBody({
                                Data: lJSONObject_DataSet
                            })
                            if (res.Status != 'success') {
                                this.$message({
                                    message: '日志保存失败，请联系开发者!',
                                    type: 'error'
                                })
                            }
                        }).catch(() => { });
                    } else {
                        this.$message({
                            message: '未查询出可导出的数据!',
                            type: 'warning'
                        })
                    }
                } else {
                    this.isExport = false;
                    this.$message({
                        message: '未查询出可导出的数据!',
                        type: 'warning'
                    })
                }
            } catch (error) {
                console.error(error);
                this.$message({
                    message: '系统错误，请联系开发者!',
                    type: 'error'
                })
                this.isExport = false;
            }
        },
        async getTreeData() {// 获取树状图数据
            if (!$('#tree').data('options')) return
            try {
                const { tableName, nodeCode } = $('#tree').data('options');
                const data = await generalApi.generalQueryForObtainingTrees({
                    TableName: tableName,
                    NodeCode: nodeCode
                })
                this.treeData = data;
            } catch (error) {
                console.error(error);
                this.$message({
                    message: '系统错误，请联系开发者!',
                    type: 'error'
                })
            }
        },
        async getColumn(is = true) {//获取表头、权限数据
            try {
                const [data, role] = await Promise.all([
                    generalApi.generalQueryBySQLSerialNumber({
                        SQLSerialNumber: 's_base_sql_table_config',
                        Condition: utf8ToBase64(`${getCookie('user')},%${getRelativePath()}%,${getCookie('user')},%${getRelativePath()}%`),
                        ExtensionCondition: ''
                    }),
                    generalApi.generalQueryBySQLSerialNumber({
                        SQLSerialNumber: 's_base_button_config',
                        Condition: utf8ToBase64(`${getCookie('user')},${getRelativePath()}`),
                        ExtensionCondition: ''
                    }),
                ]);
                this.buttonRole = Object.entries(role[0] || {}).reduce((acc, [key, value]) => {
                    acc[key] = value === '1'; // 1 → true, 0 → false
                    return acc;
                }, {});
                if (data.length > 0) {
                    this.columns = data;
                    if (is) {//默认正常初始化查询
                        this.getList(this.form);
                    } else {//调整显示字段
                        this.isUpdate = false;
                        this.$nextTick(() => {
                            this.isUpdate = true;
                        })
                    }
                } else {
                    this.$message({
                        message: '未配置数据源，请联系开发者!',
                        type: 'error'
                    })
                }
            } catch (error) {
                console.error(error);
                this.$message({
                    message: '系统错误，请联系开发者!',
                    type: 'error'
                })
            }
        },
        async getList(data) {//获取表格数据
            this.loading = true;
            try {
                const res = await generalApi.generalPaginationQueryBySQLSerialNumber({
                    Model_Url: getRelativePath(),
                    PaginationNumber: data.PageNumber,
                    RowAmount: data.RowAmount,
                    Condition: data.Condition,
                    ExtensionCondition: data.ExtensionCondition || ''
                })
                this.loading = false;
                this.Total = res.TotalRows;//总数量
                this.tableData = res.Rows;
                this.isUpdate = false;
                this.$nextTick(() => {
                    this.isUpdate = true;
                })
            } catch (error) {
                this.loading = false;
                this.$message({
                    message: '系统错误，请联系开发者!',
                    type: 'error'
                })
            }
        },
        handleSizeChange(newSize) {//切换每页查询条数
            this.form.PageNumber = 1;
            this.form.RowAmount = newSize;
            this.getList(this.form);
        },
        handleCurrentChange(newPage) {//切换页码
            this.form.PageNumber = newPage;
            this.getList(this.form);
        },
    }
};
/**
 * add.html 配置文件
 */
const Save = {
    data() {
        return {
            action: '',//页名状态 添加 or 修改
            nodeKey: '',//主键
            loading: false,//节流
        }
    },
    mounted() {
        this.init();
    },
    methods: {
        init() {//初始化方法
            let ls_URL = window.location.href;
            this.nodeKey = getQueryObject(ls_URL, "nodeKey");
            this.action = getQueryObject(ls_URL, "action") || 'Add';

            if (this.action === 'Modify' && this.nodeKey) {//修改环境，且有值
                this.getData(this.nodeKey, () => {
                    if (typeof this.documentLoadFinished === 'function') {
                        this.documentLoadFinished();
                    }
                });
            } else if (this.action === 'Add' && this.nodeKey) { //特殊数据添加 ，树形结构
                try {
                    const { formName } = $('#form').data('options');
                    this[formName].Parent_SerialNumber = this.nodeKey
                } catch (error) { }

                if (typeof this.documentLoadFinished === 'function') {
                    this.documentLoadFinished();//页面初始化完成后调用方法
                }
            }
        },
        async getData(nodeKey, callback) {//查询待修改数据
            try {
                const { tableName, formName, primaryKey } = $('#form').data('options');
                let lJSONObject_Children = new Object();//子表数据参数

                $('#form').children().each(function () {
                    const item = $(this).data('options');
                    lJSONObject_Children[item.tableName] = {
                        formName: item.formName,
                        type: 'ChildTable'
                    }
                })

                //加上主表数据参数
                let lJSONObject_Data = new Object();
                lJSONObject_Data[tableName] = {
                    formName,
                    type: 'MainTable'
                };
                lJSONObject_Data = { ...lJSONObject_Data, ...lJSONObject_Children };

                // 存放所有请求的Promises数组
                const requests = [];
                for (let key in lJSONObject_Data) {
                    const request = generalApi.generalQueryByTableNameWithOriginal({
                        Data: key,
                        Condition: `${primaryKey}='${nodeKey}'`
                    }).then(res => {
                        if (lJSONObject_Data[key].type == 'MainTable') {
                            this[lJSONObject_Data[key].formName] = res[0];
                        } else {
                            this[lJSONObject_Data[key].formName] = res;
                        }
                    }).catch(xhr => {
                        this.$message.error("系统错误，请联系开发者!");
                        throw xhr; // 抛出错误以便Promise.all捕获
                    })
                    requests.push(request);
                }

                // 等待所有请求完成
                await Promise.all(requests);

                //所有请求完成后执行函数
                if (typeof callback === 'function') {
                    callback();
                }
            } catch (error) {
                console.error(error);
                this.$message.error("系统错误，请联系开发者!")
            }
        },
        handleAdd(formName) {//添加数据
            try {
                if (this.action === 'Add') {//添加
                    this[formName].push({});
                } else if (this.action === 'Modify') {//修改时需要外键
                    const { primaryKey } = $('#form').data('options');
                    let lJSONObject_Data = new Object();
                    lJSONObject_Data[primaryKey] = this.nodeKey;
                    this[formName].push(lJSONObject_Data);
                }
            } catch (error) {
                console.error(error);
                this.$message.error("系统错误，请联系开发者!");
            }
        },
        handleRemove(formName, min = 1) {//删除数据
            try {
                if (this.action === 'Add') {
                    if (this[formName].length > min) {
                        this[formName].pop();
                    } else {
                        this.$message({
                            message: '不能在删除了',
                            type: 'warning'
                        })
                    }
                } else if (this.action === 'Modify') {
                    if (this[formName].filter(item => item.Row_Status != '1').length > min) {
                        let i = this[formName].filter(item => item.Row_Status != '1').length - 1
                        let obj = this[formName].filter(item => item.Row_Status != '1')[i]
                        if (!Object.keys(obj).some(item => item.includes('_Original'))) {
                            this[formName].pop();
                        } else {
                            this.$confirm('该操作将删除此条数据,是否继续?', '提示', {
                                confirmButtonText: '确定',
                                cancelButtonText: '取消',
                                type: 'warning',
                            }).then(() => {
                                this[formName].filter(item => item.Row_Status != '1')[i].Row_Status = '1'
                            }).catch(() => {
                                this.$message({
                                    type: 'warning',
                                    message: '已取消删除'
                                });
                            });
                        }
                    } else {
                        this.$message({
                            message: '不能在删除了',
                            type: 'warning'
                        })
                    }
                }
            } catch (error) {
                console.error(error);
                this.$message.error("系统错误，请联系开发者!");
            }
        },
        generateStructure() { //生成提交结构
            const { tableName, formName, primaryKey } = $('#form').data('options');
            let data = [{ tableName, formName, primaryKey }];
            //获取子表数据
            $('#form').children().each(function () {
                data.push($(this).data('options'));
            })

            //存在子表时
            if (data.length > 1) {
                const map = {};
                data.forEach(item => {
                    map[item.tableName] = { ...item };
                });
                data.forEach(item => {
                    const parentTableName = item.parentTableName;
                    if (parentTableName && map[parentTableName]) {
                        // 如果父对象存在，则将当前对象放入父对象的 children 数组
                        if (!this[map[parentTableName]['formName']].hasOwnProperty('Children')) {
                            this[map[parentTableName]['formName']].Children = new Object();
                        }
                        this[map[parentTableName]['formName']].Children[item.tableName] = this[map[item.tableName]['formName']].map(obj => {
                            if (!obj.Enterprise_Info_SerialNumber) {
                                obj.Enterprise_Info_SerialNumber = getCookie('enterprise');
                            }
                            return obj;
                        });
                    }
                });
            }

            let lJSONObject_DataSet = new Object();
            if (this.action == 'Add') {
                //带父主键时
                if (this.nodeKey) {
                    this[formName].Parent_SerialNumber = this.nodeKey;
                }

                // 主表关联企业编号
                this[formName]['Enterprise_Info_SerialNumber'] = getCookie('enterprise');

                let lJSONObject_Add = new Object();
                lJSONObject_Add[tableName] = [this[formName]]

                lJSONObject_DataSet = {
                    Add: lJSONObject_Add
                }
            } else if (this.action == 'Modify') {
                const { add, modify } = this.deal(this[formName]);

                let lJSONObject_Modify = new Object();
                lJSONObject_Modify[tableName] = [modify];

                lJSONObject_DataSet = {
                    Modify: lJSONObject_Modify, Add: {}
                }

                if (add != null) {
                    lJSONObject_DataSet.Add[tableName] = [add];
                }
            }

            let Operation_Main = JSON.stringify(deepClone(lJSONObject_DataSet));
            lJSONObject_DataSet['Add']['base_operation_log'] = [{
                Operation_Type: '0',
                Operation_Path: getRelativePath(),
                Operation_Description: '保存（新增/修改）数据',
                Operation_Main,
                Operation_Interface: "generalSaveByRequestBody",
                Operation_IP: getIpAddress()
            }]
            return lJSONObject_DataSet;
        },
        async handleSubmit() { //点击提交
            const allValid = await this.validateAllForms();
            if (allValid) {
                this.loading = true;
                try {
                    const lJSONObject_DataSet = this.generateStructure();
                    const res = await generalApi.generalSaveByRequestBody({
                        Data: lJSONObject_DataSet
                    })
                    if (res.Status == "success") {
                        this.$message.success("提交成功");
                        window.location.href = './index.html';
                    } else {
                        this.$message.error("提交失败，请重试！");
                    }
                    this.loading = false;
                } catch (error) {
                    console.error(error);
                    this.$message.error("系统错误，请联系开发者!")
                    this.loading = false;
                }
            } else {
                this.$message({
                    message: '存在未填写的必填项！',
                    type: 'warning'
                });
            }
        },
        deal(form) {  //将待提交的数据中添加和修改分离出来
            const add = deepClone(form), modify = deepClone(form);
            try {
                for (let key in form.Children) {
                    let add_Data = [], modify_Data = [];
                    for (const i in modify.Children[key]) {
                        const obj = modify.Children[key][i];
                        if (!Object.keys(obj).some(item => item.includes('_Original'))) {
                            add_Data.push(obj);
                        } else {
                            modify_Data.push(obj);
                        }
                    }
                    add.Children[key] = add_Data;
                    modify.Children[key] = modify_Data;
                }
                let lb_is = true;
                for (let key in add.Children) {
                    if (add.Children[key].length > 0) {
                        lb_is = false;
                    }
                }
                if (lb_is) {
                    return { add: null, modify };
                }
                return { add, modify };
            } catch (error) {
                return { add: null, modify };
            }
        },
        async validateAllForms() { //校验方法
            //获取当前页面上所有的Elform
            let forms = [];
            for (let key in this.$refs) {
                const ref = this.$refs[key];
                if (ref.$options && ref.$options.name == 'ElForm') {
                    forms.push(ref);
                }
            }
            //判断每个Elform的校验是否通过
            let isfail = false;
            for (const form of forms) {
                try {
                    await form.validate();
                } catch (error) {
                    isfail = true;
                }
            }
            if (isfail) {
                return false;
            }
            return true;
        },
        handleBack() {
            window.location.href = 'index.html'
        }
    }
}
/**
 * 上传图片组件
 */
Vue.component('yl-upload', {
    template: `<div :style="{display:drag?'block':'inline-block'}">
    <template v-if="!drag">
    <div class="preview" v-if="modelValue!=''">
        <el-image @error="handleImageError" :ref="'previewImage' + id" class="el-upload-list__item-thumbnail" style="width: 148px; height: 148px" 
            :src="base64?modelValue:imageApi + modelValue" fit="contain" :preview-src-list="fileList.map(i => i.url)"></el-image>
        <span class="el-upload-list__item-actions">
            <span @click="handlePictureCardPreview" style="cursor: pointer;"><i class="el-icon-zoom-in"></i></span>
            <span @click="handleRemove" style="cursor: pointer;"><i class="el-icon-delete"></i></span>
        </span>
    </div>
    <el-upload :disabled="loading" v-else class="upload-demo" :show-file-list="false" :on-change="handleChange"
        list-type="picture-card" action="#" accept="image/*" :auto-upload="false" :file-list="fileList">
        <i slot="default" :class="loading?'el-icon-loading':'el-icon-plus'"></i>
    </el-upload>
    <div v-if="slider" class="el-upload__tip" slot="tip">
        <div v-show="quality < 100">当前图片压缩至{{quality}}%</div>
        <el-slider :min="1" style="width:148px" v-model="quality" :format-tooltip="formatTooltip"></el-slider>
    </div>
    </template>
    <template v-else>
    <el-upload class="upload-demo" :accept="accept" :multiple="limit > 1" drag :on-change="handleChange"
        :http-request="customUpload" :file-list="fileList" :on-success="handleSuccess" :show-file-list="showFileList"
        :limit="limit" :on-remove="handleRemove" :on-exceed="handleExceed" :on-preview="handlePreview">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处上传，待点击<em>提交</em>后保存</div>
    </el-upload>
    </template></div>`,
    props: {
        accept: {
            type: String,
            default: '*/*'
        },
        value: {
            type: String,
            default: ''
        },
        file: {
            type: Array,
            default: function () {
                return []
            }
        },
        base64: {
            type: Boolean,
            default: false
        },
        slider: {
            type: Boolean,
            default: false
        },
        drag: {
            type: Boolean,
            default: false
        },
        limit: {
            type: Number,
            default: 1
        },
        showFileList: {
            type: Boolean,
            default: true
        },
        client: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            id: createUniqueString(),
            modelValue: this.value,
            fileList: [],
            loading: false,
            quality: 100,
        }
    },
    watch: {
        value(newVal) {
            if (this.modelValue == newVal) return;
            this.modelValue = newVal;
            if (newVal && !this.loading) {
                this.fileList.push({ name: newVal, url: (this.base64 ? '' : imageApi) + newVal });
            }
        },
        modelValue(newVal) {
            this.$emit('input', newVal);
        },
        file(val) {
            if (val.length > 0 && this.fileList.length == 0) {
                this.fileList = val;
            }
        }
    },
    mounted() {
        this.file.forEach(item => {
            this.fileList.push(item);
        })
    },
    methods: {
        handleImageError() {
            console.log('图片加载失败');
        },
        formatTooltip(val) {
            return '图片压缩比例：' + val + '%';
        },
        async handleChange(file) {
            const { raw } = file;
            const that = this;
            if (this.drag) { //上传文件
                if (!file.name.includes('（上传中）') && !file.name.includes('（磁盘文件名')) {
                    file.name = file.name + "（上传中）";
                }
            } else { //上传图片
                new Compressor(raw, {
                    quality: that.quality / 100,
                    success(file) {
                        if (raw.type == 'image/gif') {
                            file = raw
                        }
                        const validTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif']
                        if (!validTypes.includes(file.type)) {
                            that.$message.error({ message: '仅支持 JPG / PNG / WEBP 格式的图片', duration: 1500 });
                            return false
                        } else if (file.size / 1024 / 1024 > 8) {
                            that.$message.error({ message: '图片大小不能超过8MB！', duration: 1500 })
                            return false
                        }
                        that.loading = true;
                        that.$emit('progress', that.loading);
                        const formData = new FormData();
                        formData.append('file', file, file.name);
                        let oFileReader = new FileReader();
                        oFileReader.readAsDataURL(file);
                        oFileReader.onload = async function (e) {
                            if (!that.base64) {
                                that.$emit('progress', that.loading);
                                try {
                                    const res = await generalApi[(that.client ? 'generalUploadStreamWithClient' : 'generalUploadStream')](file);
                                    if (res.status == 'success') {
                                        that.$emit("success", file, res)
                                        that.modelValue = res.fileName;
                                        that.$message.success({ message: '上传成功', duration: 1500 })
                                    } else {
                                        that.$message.error({ message: '上传失败', duration: 1500 })
                                    }
                                } catch (xhr) {
                                    console.error(xhr);
                                    if (xhr.status == 413) {
                                        that.$message.error("文件过大，上传失败!")
                                    } else {
                                        that.$message.error("系统错误，请联系开发者!")
                                    }
                                }
                                that.loading = false;
                            } else {
                                that.modelValue = e.target.result;
                                that.loading = false;
                                that.$emit('progress', that.loading);
                            }
                        }
                        oFileReader.onerror = function (error) {
                            console.error(error);
                            that.$message({
                                message: '系统错误，请联系开发者!',
                                type: 'error'
                            })
                        };
                    },
                    error(err) {
                        console.error(err.message);
                        that.$message.error({ message: '上传失败，图片未加载成功！', duration: 1500 })
                    },
                });
            }
        },
        handlePictureCardPreview() { //预览图片
            this.$refs['previewImage' + this.id].clickHandler();
        },
        handleClear() { //清空文件
            this.$emit("clear", this.fileList)
            this.fileList = [];
        },
        handleRemove(file, fileList = []) {//删除图片
            this.fileList = fileList;
            this.$emit("remove", file);
            this.modelValue = '';
        },
        handlePreview(file) {
            this.$emit("preview", file)
        },
        handleExceed() {
            this.$message({
                type: 'warning',
                message: '最大上传数:' + this.limit
            });
        },
        async customUpload(options) {
            const { file } = options;
            this.loading = true;
            this.$emit('progress', this.loading);
            try {
                const res = await generalApi[(this.client ? 'generalUploadStreamWithClient' : 'generalUploadStream')](file);
                if (res.status == 'success') {
                    this.fileList.push(file);
                    this.$emit("success", file, res)
                    this.modelValue = res.fileName;
                    options.onSuccess(res)
                    this.$message.success({ message: '上传成功', duration: 1500 })
                } else {
                    this.$message.error({ message: '上传失败', duration: 1500 });
                }
            } catch (xhr) {
                console.error(xhr);
                if (xhr.status == 413) {
                    this.$message.error("文件过大，上传失败!")
                } else {
                    this.$message.error("系统错误，请联系开发者!")
                }
            }
            this.loading = false;
            this.$emit('progress', this.loading);
        },
        handleSuccess(result, file) {
            if (result) {
                file.name = file.name.replace('（上传中）', '（磁盘文件名:' + result.fileName + '）');
                file.Attachment_URL = result.fileName;
                const index = this.fileList.findIndex(f => f.uid === file.uid);
                if (index !== -1) {
                    this.$set(this.fileList, index, file);
                }
            }
        },
    }
})

/**
 * 地图组件，默认高度500px
 */
Vue.component('yl-map', {
    template: `<div class="map">
    <div :id="id" :style="{ height }"></div>
    <div v-if="!disabled" class="input-card" >
        <p style="margin-bottom: 5px; font-weight: 600;line-height: 21px;">操作</p>
        <el-button :type="isDraw?'warning':'primary'" round size="mini" @click="handleDrawPolygon">{{isDraw?'双击结束':'绘制区域'}}</el-button>
        <el-button type="danger" round size="mini" @click="handleCleanPolygon">清空区域</el-button>
    </div></div>`,
    props: {
        height: {
            type: String,
            default: '500px'
        },
        center: {
            type: Array,
            default: function () {
                return [116.397428, 39.90923]
            }
        },
        disabled: {
            type: Boolean,
            default: false,
        },
        value: {
            type: String,
            default: "[]",
        },
    },
    data() {
        return {
            id: 'map' + createUniqueString(),
            map: null,//地图
            mouseTool: null,//地图绘制工具
            isDraw: false,//是否绘制
            polygons: [],//区域
            modelValue: [],//绘制结束
        }
    },
    watch: {
        value(newVal) {
            this.modelValue = JSON.parse(newVal);
            try {
                JSON.parse(newVal).forEach(item => {
                    this.addPolygon(item);
                })
            } catch (error) { }
        },
        modelValue(newVal) {
            this.$emit('input', JSON.stringify(newVal));
            this.$emit('change', JSON.stringify(newVal));
        },
    },
    created() {
        loadScript(`https://webapi.amap.com/maps?v=2.0&key=${mapJsKey}&plugin=AMap.MouseTool`, () => {
            this.map = new AMap.Map(this.id, {
                viewMode: '2D', //默认使用 2D 模式
                zoom: 11, //地图级别
                center: this.center, //地图中心点
            })
            //添加坐标点
            this.modelValue.forEach(item => {
                this.addPolygon(item);
            })
            this.mouseTool = new AMap.MouseTool(this.map);
            this.mouseTool.on('draw', (event) => {//监听绘制结果
                const path = event.obj.getPath();
                this.mouseTool.close(true);
                this.isDraw = false;
                this.addPolygon([path.map(i => [i.KL, i.kT])]);
                this.modelValue.push(path.map(i => [i.KL, i.kT]));
                this.$message({
                    message: '绘制区域结束',
                    type: 'success'
                });
            })
        })
    },
    methods: {
        updateCenter(center) {//更新地图中心点
            this.map.setCenter(center);
        },
        handleDrawPolygon() {//绘制区域
            if (!this.isDraw) {
                this.isDraw = true;
                this.mouseTool.polygon({
                    fillColor: '#1791fc',
                    strokeOpacity: 1,
                    fillOpacity: 0.5,
                    strokeColor: "#FF33FF",
                    strokeWeight: 1,
                    strokeStyle: "solid",
                })
                this.$message({
                    message: '开始绘制区域',
                    type: 'success'
                });
            } else {
                this.$message({
                    message: '区域绘制中，双击地图结束',
                    type: 'warning'
                });
            }
        },
        handleCleanPolygon() {//清空
            this.$confirm('此操作将清空全部区域, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.polygons.forEach(polygon => {
                    this.map.remove(polygon); // 逐个移除
                });
                this.polygons.length = 0; // 清空数组
                this.modelValue = [];
            }).catch(() => { });
        },
        addPolygon(data) { //给地图添加区域
            let polygon = new AMap.Polygon({
                path: data,
                fillColor: '#ccebc5',
                strokeOpacity: 1,
                fillOpacity: 0.5,
                strokeColor: '#2b8cbe',
                strokeWeight: 1,
                strokeStyle: 'solid',
                strokeDasharray: [5, 5],
            });
            if (!this.disabled) {
                polygon.on('mouseover', () => {
                    polygon.setOptions({
                        fillOpacity: 0.7,
                        fillColor: '#7bccc4'
                    })
                })
                polygon.on('mouseout', () => {
                    polygon.setOptions({
                        fillOpacity: 0.5,
                        fillColor: '#ccebc5'

                    })
                })
                polygon.on('click', () => {
                    this.$confirm('此操作将删除该区域, 是否继续?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        this.$message({
                            type: 'success',
                            message: '删除成功!'
                        });
                        this.map.remove(polygon);
                        const index = this.polygons.indexOf(polygon);
                        if (index !== -1) this.polygons.splice(index, 1);
                        this.modelValue = this.polygons.map(i => i.getPath()[0].map(x => [x.KL, x.kT]));
                    }).catch(() => { });
                })
            }
            this.polygons.push(polygon);
            this.map.add(polygon);
            this.map.setFitView(null, false, [60, 60, 60, 60]);
        }
    }
})

/**
 * 富文本编辑器
 */
Vue.component('yl-text-editor', {
    template: `<div id="editor—wrapper">
    <div :id="'toolbar-container' + id"><!-- 工具栏 --></div>
    <div :id="'editor-container' + id"><!-- 编辑器 --></div></div>`,
    props: {
        value: {
            type: String,
            default: ''
        },
        placeholder: {
            type: String,
            default: '请填写富文本内容...'
        },
        max: {
            type: Number,
            default: 0,
        },
        type: {
            type: String,
            default: 'default'
        },
        disabled: {
            type: Boolean,
            default: false,
        }
    },
    data() {
        return {
            id: createUniqueString(),
            editor: null,//富文本编辑器核心
            modelValue: this.value,//文本内容
        }
    },
    mounted() {
        this.init();
        if (this.value != '' && this.editor.getHtml() != this.value) {
            this.editor.setHtml(this.value);
        }
        if (this.editor.isDisabled() && !this.disabled) {
            this.editor.enable();
        } else if (!this.editor.isDisabled() && this.disabled) {
            this.editor.disable();
        }
    },
    watch: {
        modelValue(newVal) {//组件双向绑定
            this.$emit('input', newVal);
        },
        value(newVal) {//更新文本内容
            if (this.editor.getHtml() != newVal) {
                this.editor.setHtml(newVal);
            }
        },
        disabled(disabled) {//动态禁用状态
            if (this.editor.isDisabled() && !disabled) {
                this.editor.enable();
            } else if (!this.editor.isDisabled() && disabled) {
                this.editor.disable();
            }
        }
    },
    computed: {
        maxLength() {//最大文字限制，默认0为无限制
            return this.max == 0 ? {} : { maxLength: this.max };
        },
        mode() {//是否开启简洁模式
            return this.type == 'default' || this.type == 'simple' ? this.type : 'default';
        }
    },
    methods: {
        init() {
            const { createEditor, createToolbar } = window.wangEditor;
            const that = this;
            const editorConfig = {
                placeholder: this.placeholder,
                ...this.maxLength,
                readOnly: this.disabled,
                MENU_CONF: {
                    uploadImage: {//上传图片
                        customUpload(file, insertFn) {
                            new Compressor(file, {
                                quality: 1,
                                success(file) {
                                    const formData = new FormData();
                                    formData.append('file', file, file.name);
                                    let oFileReader = new FileReader();
                                    oFileReader.readAsDataURL(file);
                                    oFileReader.onload = async function (e) {
                                        const res = await generalApi.generalUploadStream(file);
                                        if (res.status == 'success') {
                                            insertFn(imageApi + res.fileName, "", "");
                                        } else {
                                            that.$message.error("上传失败!")
                                        }
                                    };
                                    oFileReader.onerror = function (error) {
                                        console.error(error);
                                        that.$message({
                                            message: '系统错误，请联系开发者!',
                                            type: 'error'
                                        })
                                    };
                                },
                                error(error) {
                                    console.error(error);
                                    that.$message({
                                        message: '系统错误，请联系开发者!',
                                        type: 'error'
                                    })
                                },
                            })
                        }
                    },
                    uploadVideo: {//上传视频
                        async customUpload(file, insertFn) {
                            try {
                                const res = await generalApi.generalUploadStream(file);
                                if (res.status == 'success') {
                                    insertFn(imageApi + res.fileName, "", "");
                                } else {
                                    that.$message.error("上传失败!")
                                }
                            } catch (xhr) {
                                if (xhr.status == 413) {
                                    that.$message.error("视频过大，上传失败!")
                                } else {
                                    that.$message.error("系统错误，请联系开发者!")
                                }
                            }
                        }
                    }
                },
                onChange: (editor) => {
                    this.modelValue = editor.getHtml();
                },
                onDestroyed(editor) {
                    editor.destroy();
                }
            }
            const editor = createEditor({
                selector: `#editor-container${this.id}`,
                html: '<p><br></p>',
                config: editorConfig,
                mode: this.mode,
            })
            createToolbar({
                editor: editor,
                selector: `#toolbar-container${this.id}`,
                config: {},
                mode: this.mode,
            })
            this.editor = Object.seal(editor);
        }
    }
})

/**
 * 配置各个角色是否展示某字段（自己配置）
 */
Vue.component('field-config', {
    template: `<el-dialog title="字段配置" :visible.sync="visibleDialog" width="700px" :close-on-click-modal="false" :destroy-on-close="true">
    <el-checkbox-group id="field_config" v-model="checkList">
        <el-checkbox :disabled="checkList.length == 1 && checkList.some(i => i == item.SQL_Model_List_SerialNumber)" :label="item.SQL_Model_List_SerialNumber" border v-for="(item,index) in field" :key="index">{{item.Column_Comment}}</el-checkbox>
    </el-checkbox-group>
    <span slot="footer" class="dialog-footer">
        <el-button @click="$emit('update:visible',false)">取消</el-button>
        <el-button type="primary" :loading="loading" @click="submitForm()">保存</el-button>
    </span></el-dialog>`,
    props: ['value', 'visible'],
    data() {
        return {
            visibleDialog: false,
            checkList: [],
            field: [],
            loading: false
        }
    },
    watch: {
        visible() {
            this.visibleDialog = this.visible
        },
        visibleDialog(val) {
            this.$emit('update:visible', val)
            this.dialogVisible = true;
            this.getData();
        },
    },
    methods: {
        async getData() {//查询
            try {
                const data = await generalApi.generalQueryBySQLSerialNumber({
                    SQLSerialNumber: 's_base_column_config',
                    Condition: utf8ToBase64(getCookie('user') + "," + getCookie('user') + "," + getRelativePath()),
                    ExtensionCondition: ''
                })
                this.field = data;
                this.checkList = data.filter(i => i.isShow == '1').map(i => i.SQL_Model_List_SerialNumber);
            } catch (error) {
                console.error(error);
                this.$message({
                    message: '系统错误，请联系开发者!',
                    type: 'error'
                })
            }
        },
        async submitForm() {//提交
            this.loading = true;
            let fieldList1 = this.field.filter(i => !this.checkList.some(x => x == i.SQL_Model_List_SerialNumber)).map(item => item.SQL_Model_List_SerialNumber);//不显示
            let fieldList2 = this.field.filter(i => this.checkList.some(x => x == i.SQL_Model_List_SerialNumber)).map(item => item.SQL_Model_List_SerialNumber);//显示
            let str = this.field.map(item => `'${item.SQL_Model_List_SerialNumber}'`).join(',');

            try {
                const data = await generalApi.generalQueryByTableNameWithOriginal({
                    Data: 'base_column_config',
                    Condition: `SQL_Model_List_SerialNumber IN (${str}) AND Creater_SerialNumber='${getCookie('user')}'`
                })
                let base_column_config = [];
                fieldList1.forEach(item => {
                    let obj = data.filter(i => i.SQL_Model_List_SerialNumber == item)[0];
                    if (obj) {//有他，状态改为0
                        obj.Row_Status = '0';
                    } else {//没有他，添加
                        base_column_config.push({
                            SQL_Model_List_SerialNumber: item,
                            Model_Url: getRelativePath()
                        })
                    }
                })
                fieldList2.forEach(item => {
                    let obj = data.filter(i => i.SQL_Model_List_SerialNumber == item)[0];
                    if (obj) { //有他，状态改为1
                        obj.Row_Status = '1';
                    }
                })
                //是否有需提交的数据
                if (base_column_config.length > 0 || data.length > 0) {
                    let lJSONObject_DataSet = {
                        Add: { base_column_config },
                        Modify: { base_column_config: data }
                    }

                    let Operation_Main = JSON.stringify(deepClone(lJSONObject_DataSet));
                    lJSONObject_DataSet['Add']['base_operation_log'] = [{
                        Operation_Type: '0',
                        Operation_Path: getRelativePath(),
                        Operation_Description: '配置表格字段展示数据',
                        Operation_Main,
                        Operation_Interface: "generalSaveByRequestBody",
                        Operation_IP: getIpAddress()
                    }]

                    const res = await generalApi.generalSaveByRequestBody({
                        Data: lJSONObject_DataSet
                    })
                    this.loading = false;
                    if (res.Status == "success") {
                        this.$emit('success');
                        this.$emit('update:visible', false);
                    } else {
                        this.$message.error("操作失败，请重试！");
                    }
                } else {
                    this.loading = false;
                    this.$emit('success');
                    this.$emit('update:visible', false);
                }
            } catch (error) {
                console.error(error);
                this.$message.error("系统错误，请联系开发者!")
            }
        }
    }
})

/**
 * 移动端底部导航栏
 */
Vue.component('tab-bar', {
    template: `<div class="flex bg-white fixed-bottom shadow" style="height: 120rem;">
    <div @click="switchTab(item,index)" v-for="(item,index) in list" :key="index" class="w-100 pt-1 flex flex-column align-center">
        <el-image :style="{width:'25px',height:'25px'}"
            :src="absolutepath() + item[index == selected ? 'selectedIconPath' : 'iconPath']"></el-image>
        <span :style="{ color: index == selected ? selectedColor : color }" class="font-small">
            {{item.text}}
        </span>
    </div></div>`,
    props: {
        selected: {
            type: Number,
            default: 0
        },
    },
    data() {
        return {
            color: "#7A7E83",
            selectedColor: "#3cc51f",
            borderStyle: "black",
            backgroundColor: "#ffffff",
            list: [{
                pagePath: "pages/index/index",
                iconPath: "admin/icon/index.png",
                selectedIconPath: "admin/icon/index-select.png",
                text: "首页"
            }, {
                pagePath: "pages/index/shopcar",
                iconPath: "admin/icon/shopcar.png",
                selectedIconPath: "admin/icon/shopcar-select.png",
                text: "购物车"
            }, {
                pagePath: "pages/my/my",
                iconPath: "admin/icon/my.png",
                selectedIconPath: "admin/icon/my-select.png",
                text: "我的"
            }]
        }
    },
    methods: {
        switchTab(item, index) {
            if (index == this.selected) return;
            window.location.href = `../../${item.pagePath}.html`;
        }
    }
})


/**
 * 移动端选项卡
 */
Vue.component('tab-nav', {
    template: `<div class="bg-white flex shadow" style="height: 80rem;">
    <div class="w-100 font flex" :class="flex" style="line-height: 80rem;">
        <span @click="handleChange(item)" class="flex-shrink text-ellipsis text-center" style="width: 20%;" v-for="(item, index) in options.filter((i,id) => id < 5)" :key="index"
            :class="{ 'text-success': isActive == item[value],'text-dark':isActive != item[value] }">{{item[label]}}</span>
    </div>
    <div @click="drawer = !drawer" class="flex-shrink h2 mx-2" style="line-height: 80rem;" v-if="options.length > 5">
        <i class="el-icon-menu text-dark"></i>
    </div>
    <el-drawer :visible.sync="drawer" direction="ttb" :show-close="false">
        <div class="w-100 flex flex-wrap pb-2">
            <div @click="handleChange(item)" class="font-sm mt-2 ml-2 px-2 py-1 rounded-circle flex-shrink text-center border border-success" v-for="(item, index) in options" :key="index" 
                :class="{ 'text-success': isActive == item[value],'text-dark':isActive != item[value]  }">
                <span>{{item[label]}}</span>
            </div>
        </div>
    </el-drawer></div>`,
    props: {
        label: {
            type: String,
            default: 'label'
        },
        value: {
            type: String,
            default: 'value'
        },
        options: {
            type: Array,
            default: function () {
                return []
            }
        },
        loading: {
            type: Boolean,
            default: false
        },
        flex: {
            type: String,
            default: ''
        }
        ,active: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
            isActive: '',
            drawer: false,// 更多类别
        }
    },
    mounted(){
        this.isActive = this.active || '';
    },
    watch: {
        active(val){
            this.isActive = val || '';
        }
    },
    methods: {
        handleChange(item) {
            if (this.isActive == item[this.value] || this.loading) return;//不能重复点击一样的类别
            this.isActive = item[this.value];
            this.$emit('change', item);
        }
    },
})


/**
 * 模拟uniapp的uni.showToast，不带icon
 */
const showToast = Vue.component('show-toast', {
    template: `<div :style="style" v-show="show" style="z-index: 9000;">
    <div :style="textStyle">
        {{title}}
    </div></div>`,
    props: {
        title: {
            type: String,
            default: ''
        },
        show: {
            type: Boolean,
            default: false
        }
    },
    computed: {
        style() {
            return {
                position: 'fixed',
                top: 0,
                left: 0,
                width: '100%',
                height: '100%',
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center'
            }
        },
        textStyle() {
            return {
                background: '#000',
                opacity: '.65',
                color: '#fff',
                padding: '10px 20px',
                maxWidth: '40%',
                fontSize: '14px',
                borderRadius: '5px',
                textAlign: 'center'
            }
        },
    },
})

/**
 * 模拟uniapp的uni.showModal，不带icon
 */
const showModal = Vue.component('show-modal', {
    template: `<div :style="style" v-show="show" style="z-index: 8000; animation: fadeIn 0.3s;">
    <div style="width: 80vw;" :style="textStyle">
        <div style="padding: 30px 20px;">
            <span class="font-md font-weight-bolder">{{ title }}</span>
            <div class="font-md text-muted mt-2">{{ content }}</div>
            <div v-show="editable" class="font-md text-muted mt-2">
                <el-input v-model="value" :placeholder="placeholderText"></el-input>
            </div>
        </div>
        <div class="border-top flex font-md font-weight-bolder">
            <div class="w-100 py-3 border-right" style="cursor: pointer;" @click="handleCancel">{{ cancelText }}</div>
            <div class="w-100 py-3" style="color: rgb(87, 107, 149); cursor: pointer;" @click="handleConfirm">{{ confirmText }}</div>
        </div>
    </div></div>`,
    props: {
        title: {
            type: String,
            default: '提示'
        },
        content: {
            type: String,
            default: ''
        },
        cancelText: {
            type: String,
            default: '取消'
        },
        confirmText: {
            type: String,
            default: '确定'
        },
        placeholderText: {
            type: String,
            default: '请输入...'
        },
        show: {
            type: Boolean,
            default: false
        },
        editable: { // 显示输入框
            type: Boolean,
            default: false
        },
        onCancel: { // 取消回调
            type: Function,
            default: () => { }
        },
        onConfirm: { // 确定回调
            type: Function,
            default: () => { }
        },
        showConfirm: { // 自动关闭
            type: Boolean,
            default: true
        }
    },
    computed: {
        style() {
            return {
                position: 'fixed',
                top: 0,
                left: 0,
                width: '100%',
                height: '100%',
                display: 'flex',
                justifyContent: 'center',
                backgroundColor: 'rgba(0, 0, 0, 0.6)',
                alignItems: 'center'
            }
        },
        textStyle() {
            return {
                background: '#fff',
                borderRadius: '15px',
                textAlign: 'center'
            }
        },
    },
    data() {
        return {
            value: '',
        }
    },
    methods: {
        handleCancel() {
            this.onCancel(); // 触发取消回调
            this.show = false; // 关闭弹窗 
        },
        handleConfirm() {
            const { value, close } = this;
            this.onConfirm({ value, close }); // 触发确定回调
            if (this.showConfirm) {
                this.show = false; // 关闭弹窗 
            }
        },
        close() {
            this.show = false; // 关闭弹窗
        }
    }
})


/**
 * 挂载到Vue组件上
 */
Vue.use({
    install(Vue) {
        let Com = Vue.extend(showToast); //拓展方法，showToast是独立的组件，extend的作用是将showToast与Vue关联起来
        let vt = new Com().$mount(); //组件实例化，使用$mount可以获取showToast组件vm层
        document.body.appendChild(vt.$el);

        Vue.prototype.$showToast = function (data) {
            if (!vt.show) {
                if (isNaN(data.duration)) {
                    data.duration = 1500
                }
                vt.show = true;
                vt.title = data.title;
                const timer = setTimeout(() => {
                    vt.show = false;
                    clearTimeout(timer);
                }, data.duration)
            }
        }

        let Mod = Vue.extend(showModal);
        let vm = new Mod().$mount();
        document.body.appendChild(vm.$el);

        Vue.prototype.$showModal = function (data) {
            if (!vm.show) {
                vm.show = true;
                vm.title = data.title;
                vm.content = data.content;
                if (data.cancelText != undefined) { vm.cancelText = data.cancelText }
                if (data.confirmText != undefined) { vm.confirmText = data.confirmText }
                if (data.showConfirm != undefined) { vm.showConfirm = data.showConfirm }
                vm.placeholderText = data.placeholderText;
                vm.editable = data.editable;
                vm.onCancel = data.onCancel || (() => { }); // 传入取消回调
                vm.onConfirm = data.onConfirm || (() => { }); // 传入确定回调
            }
        }
    }
});
